home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.001 / tcpdump-~ / tcpdump-3.0.2-linux / tcpdump-3.0.2 / tcpdump.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-25  |  8.7 KB  |  416 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. char copyright[] =
  23.     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994\nThe Regents of the University of California.  All rights reserved.\n";
  24. static  char rcsid[] =
  25.     "@(#)$Header: tcpdump.c,v 1.93 94/06/10 17:01:44 mccanne Exp $ (LBL)";
  26. #endif
  27.  
  28. /*
  29.  * tcpdump - monitor tcp/ip traffic on an ethernet.
  30.  *
  31.  * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
  32.  * Mercilessly hacked and occasionally improved since then via the
  33.  * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
  34.  */
  35.  
  36. #include <sys/types.h>
  37. #include <sys/time.h>
  38.  
  39. #include <netinet/in.h>
  40.  
  41. #include <pcap.h>
  42. #include <signal.h>
  43. #include <stdio.h>
  44. #ifdef __STDC__
  45. #include <stdlib.h>
  46. #endif
  47. #include <unistd.h>
  48. #include <string.h>
  49.  
  50. #include "interface.h"
  51. #include "addrtoname.h"
  52.  
  53. int fflag;            /* don't translate "foreign" IP address */
  54. int nflag;            /* leave addresses as numbers */
  55. int Nflag;            /* remove domains from printed host names */
  56. int pflag;            /* don't go promiscuous */
  57. int qflag;            /* quick (shorter) output */
  58. int tflag = 1;            /* print packet arrival time */
  59. int eflag;            /* print ethernet header */
  60. int vflag;            /* verbose */
  61. int xflag;            /* print packet in hex */
  62. int Oflag = 1;            /* run filter code optimizer */
  63. int Sflag;            /* print raw TCP sequence numbers */
  64. int packettype;
  65.  
  66. int dflag;            /* print filter code */
  67.  
  68. char *program_name;
  69.  
  70. int thiszone;
  71.  
  72. SIGRET cleanup(int);
  73. extern void bpf_dump(struct bpf_program *, int);
  74.  
  75. /* Length of saved portion of packet. */
  76. int snaplen = DEFAULT_SNAPLEN;
  77.  
  78. struct printer {
  79.     pcap_handler f;
  80.     int type;
  81. };
  82.  
  83. static struct printer printers[] = {
  84.     { ether_if_print,    DLT_EN10MB },
  85.     { sl_if_print,        DLT_SLIP },
  86.     { ppp_if_print,        DLT_PPP },
  87.     { fddi_if_print,    DLT_FDDI },
  88.     { null_if_print,    DLT_NULL },
  89.     { NULL,            0 },
  90. };
  91.  
  92. static pcap_handler
  93. lookup_printer(int type)
  94. {
  95.     struct printer *p;
  96.  
  97.     for (p = printers; p->f; ++p)
  98.         if (type == p->type)
  99.             return p->f;
  100.  
  101.     error("unknown data link type 0x%x", type);
  102.     /* NOTREACHED */
  103. }
  104.  
  105. static pcap_t *pd;
  106.  
  107. #ifdef __osf__
  108. #include <sys/sysinfo.h>
  109. #include <sys/proc.h>
  110. void
  111. abort_on_misalignment()
  112. {
  113.     int buf[2];
  114.     
  115.     buf[0] = SSIN_UACPROC;
  116.     buf[1] = UAC_SIGBUS;
  117.     if (setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0) < 0) {
  118.         perror("setsysinfo");
  119.         exit(1);
  120.     }
  121. }
  122.  
  123. #endif
  124.  
  125. int
  126. main(int argc, char **argv)
  127. {
  128.     register int cnt, op;
  129.     u_long localnet, netmask;
  130.     register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName;
  131.     pcap_handler printer;
  132.     struct bpf_program fcode;
  133.     u_char *pcap_userdata;
  134.     char errbuf[PCAP_ERRBUF_SIZE];
  135.  
  136.     extern char *optarg;
  137.     extern int optind, opterr;
  138.  
  139. #ifdef __osf__
  140.     abort_on_misalignment();
  141. #endif
  142.  
  143.     cnt = -1;
  144.     device = NULL;
  145.     infile = NULL;
  146.     RFileName = NULL;
  147.     WFileName = NULL;
  148.     if ((cp = strrchr(argv[0], '/')) != NULL)
  149.         program_name = cp + 1;
  150.     else
  151.         program_name = argv[0];
  152.  
  153.     opterr = 0;
  154.     while ((op = getopt(argc, argv, "c:defF:i:lnNOpqr:s:StT:vw:xY")) != EOF)
  155.         switch (op) {
  156.         case 'c':
  157.             cnt = atoi(optarg);
  158.             break;
  159.  
  160.         case 'd':
  161.             ++dflag;
  162.             break;
  163.  
  164.         case 'e':
  165.             ++eflag;
  166.             break;
  167.  
  168.         case 'f':
  169.             ++fflag;
  170.             break;
  171.  
  172.         case 'F':
  173.             infile = optarg;
  174.             break;
  175.  
  176.         case 'i':
  177.             device = optarg;
  178.             break;
  179.  
  180.         case 'l':
  181.             setlinebuf(stdout);
  182.             break;
  183.  
  184.         case 'n':
  185.             ++nflag;
  186.             break;
  187.  
  188.         case 'N':
  189.             ++Nflag;
  190.             break;
  191.  
  192.         case 'O':
  193.             Oflag = 0;
  194.             break;
  195.  
  196.         case 'p':
  197.             ++pflag;
  198.             break;
  199.  
  200.         case 'q':
  201.             ++qflag;
  202.             break;
  203.  
  204.         case 'r':
  205.             RFileName = optarg;
  206.             break;
  207.  
  208.         case 's':
  209.             snaplen = atoi(optarg);
  210.             break;
  211.  
  212.         case 'S':
  213.             ++Sflag;
  214.             break;
  215.  
  216.         case 't':
  217.             --tflag;
  218.             break;
  219.  
  220.         case 'T':
  221.             if (strcasecmp(optarg, "vat") == 0)
  222.                 packettype = 1;
  223.             else if (strcasecmp(optarg, "wb") == 0)
  224.                 packettype = 2;
  225.             else if (strcasecmp(optarg, "rpc") == 0)
  226.                 packettype = 3;
  227.             else if (strcasecmp(optarg, "rtp") == 0)
  228.                 packettype = 4;
  229.             else
  230.                 error("unknown packet type `%s'", optarg);
  231.             break;
  232.  
  233.         case 'v':
  234.             ++vflag;
  235.             break;
  236.  
  237.         case 'w':
  238.             WFileName = optarg;
  239.             break;
  240. #ifdef YYDEBUG
  241.         case 'Y':
  242.             {
  243.             extern int yydebug;
  244.             yydebug = 1;
  245.             }
  246.             break;
  247. #endif
  248.         case 'x':
  249.             ++xflag;
  250.             break;
  251.  
  252.         default:
  253.             usage();
  254.             /* NOTREACHED */
  255.         }
  256.  
  257.     if (tflag > 0)
  258.         thiszone = gmt2local();
  259.  
  260.     if (RFileName != NULL) {
  261.         /*
  262.          * We don't need network access, so set it back to the user id.
  263.          * Also, this prevents the user from reading anyone's
  264.          * trace file.
  265.          */
  266.         setuid(getuid());
  267.  
  268.         pd = pcap_open_offline(RFileName, errbuf);
  269.         if (pd == NULL)
  270.             error(errbuf);
  271.         localnet = 0;
  272.         netmask = 0;
  273.         if (fflag != 0)
  274.             error("-f and -r options are incompatible");
  275.     } else {
  276.         if (device == NULL) {
  277.             device = pcap_lookupdev(errbuf);
  278.             if (device == NULL)
  279.                 error(errbuf);
  280.         }
  281.         pd = pcap_open_live(device, snaplen, !pflag, 1000, errbuf);
  282.         if (pd == NULL)
  283.             error(errbuf);
  284.         if (pcap_lookupnet(device, &localnet, &netmask, errbuf) < 0)
  285.             error(errbuf);
  286.         /*
  287.          * Let user own process after socket has been opened.
  288.          */
  289.         setuid(getuid());
  290.     }
  291.     if (infile)
  292.         cmdbuf = read_infile(infile);
  293.     else
  294.         cmdbuf = copy_argv(&argv[optind]);
  295.  
  296.     if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
  297.         error(pcap_geterr(pd));
  298.     if (dflag) {
  299.         bpf_dump(&fcode, dflag);
  300.         exit(0);
  301.     }
  302.     init_addrtoname(fflag, localnet, netmask);
  303.  
  304.     (void)signal(SIGTERM, cleanup);
  305.     (void)signal(SIGINT, cleanup);
  306.     (void)signal(SIGHUP, cleanup);
  307.  
  308.     if (pcap_setfilter(pd, &fcode) < 0)
  309.         error(pcap_geterr(pd));
  310.     if (WFileName) {
  311.         pcap_dumper_t *p = pcap_dump_open(pd, WFileName);
  312.         if (p == NULL)
  313.             error(pcap_geterr(pd));
  314.         printer = pcap_dump;
  315.         pcap_userdata = (u_char *)p;
  316.     } else {
  317.         printer = lookup_printer(pcap_datalink(pd));
  318.         pcap_userdata = 0;
  319.     }
  320.     if (RFileName == NULL) {
  321.         fprintf(stderr, "%s: listening on %s\n", program_name, device);
  322.         fflush(stderr);
  323.     }
  324.     if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) {
  325.         (void)fprintf(stderr, "%s: pcap_loop: %s\n",
  326.             program_name, pcap_geterr(pd));
  327.         exit(1);
  328.     }
  329.     pcap_close(pd);
  330.     exit(0);
  331. }
  332.  
  333. /* make a clean exit on interrupts */
  334. SIGRET
  335. cleanup(int signo)
  336. {
  337.     struct pcap_stat stat;
  338.  
  339.     /* Can't print the summary if reading from a savefile */
  340.     if (pd != NULL && pcap_file(pd) == NULL) {
  341.         (void)fflush(stdout);
  342.         putc('\n', stderr);
  343.         if (pcap_stats(pd, &stat) < 0)
  344.             (void)fprintf(stderr, "pcap_stats: %s\n",
  345.                 pcap_geterr(pd));
  346.         else {
  347.             (void)fprintf(stderr, "%d packets received by filter\n",
  348.                 stat.ps_recv);
  349.             (void)fprintf(stderr, "%d packets dropped by kernel\n",
  350.                 stat.ps_drop);
  351.         }
  352.     }
  353.     exit(0);
  354. }
  355.  
  356. /* Like default_print() but data need not be aligned */
  357. void
  358. default_print_unaligned(register const u_char *cp, register int length)
  359. {
  360.     register u_int i, s;
  361.     register int nshorts;
  362.  
  363.     nshorts = (u_int) length / sizeof(u_short);
  364.     i = 0;
  365.     while (--nshorts >= 0) {
  366.         if ((i++ % 8) == 0)
  367.             (void)printf("\n\t\t\t");
  368.         s = *cp++;
  369.         (void)printf(" %02x%02x", s, *cp++);
  370.     }
  371.     if (length & 1) {
  372.         if ((i % 8) == 0)
  373.             (void)printf("\n\t\t\t");
  374.         (void)printf(" %02x", *cp);
  375.     }
  376. }
  377.  
  378. void
  379. default_print(register const u_char *bp, register int length)
  380. {
  381.     register const u_short *sp;
  382.     register u_int i;
  383.     register int nshorts;
  384.  
  385.     if ((int)bp & 1) {
  386.         default_print_unaligned(bp, length);
  387.         return;
  388.     }
  389.     sp = (u_short *)bp;
  390.     nshorts = (u_int) length / sizeof(u_short);
  391.     i = 0;
  392.     while (--nshorts >= 0) {
  393.         if ((i++ % 8) == 0)
  394.             (void)printf("\n\t\t\t");
  395.         (void)printf(" %04x", ntohs(*sp++));
  396.     }
  397.     if (length & 1) {
  398.         if ((i % 8) == 0)
  399.             (void)printf("\n\t\t\t");
  400.         (void)printf(" %02x", *(u_char *)sp);
  401.     }
  402. }
  403.  
  404. void
  405. usage()
  406. {
  407.     extern char version[];
  408.  
  409.     (void)fprintf(stderr, "Version %s\n", version);
  410.     (void)fprintf(stderr,
  411. "Usage: tcpdump [-deflnOpqtvx] [-c count] [-i interface]\n");
  412.     (void)fprintf(stderr,
  413. "\t\t[-r filename] [-w filename] [expr]\n");
  414.     exit(-1);
  415. }
  416.